/*
 * Copyright 2025 The JA-SIG Collaborative. All rights reserved.
 * distributed with this file and available online at
 */
package com.lap.auth.application.dept;

import com.lap.auth.application.dept.assembler.DeptAssembler;
import com.lap.auth.application.dept.command.CreateDeptCmd;
import com.lap.auth.application.dept.command.UpdateDeptCmd;
import com.lap.auth.application.dept.dto.DeptNodeDto;
import com.lap.auth.application.dept.dto.DeptOptionDto;
import com.lap.auth.application.dept.dto.GetDeptByIdsQuery;
import com.lap.auth.domain.shared.ports.SeqService;
import com.lap.auth.domain.dept.Dept;
import com.lap.auth.domain.dept.repository.DeptRepository;
import com.lap.auth.domain.dept.service.DeptValidator;
import java.util.Collections;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

/**
 * 部门应用服务层
 *
 * <ol>
 *   <li>不谈业务规则，只谈基础规则（加密/解密是技术实现，业务不关注）
 *   <li>取数，赋值，对象转换到在这层执行
 *   <li>命名有规范，动词+领域名字
 *   <li>如查询比较多，建议分开领域QueryAppService,如:分页查询，分页查询返回关联字段
 * </ol>
 */
@RequiredArgsConstructor
@Service
public class DeptAppService {

  private final SeqService seqService;
  private final DeptAssembler assembler;
  private final DeptValidator deptValidator;
  private final DeptRepository deptRepository;

  public List<DeptNodeDto> queryDeptTree() {
    List<Dept> allList = deptRepository.findAll();
    List<DeptNodeDto> flatList = assembler.toDtoList(allList);
    return assembler.convertToTree(flatList);
  }

  public List<DeptOptionDto> queryDeptByIds(GetDeptByIdsQuery query) {
    if (CollectionUtils.isEmpty(query.getIdSet())) return Collections.emptyList();

    List<Dept> allList = deptRepository.findByIds(query.getIdSet().stream().toList());
    return assembler.toOptionDtoList(allList);
  }

  public Integer createDept(CreateDeptCmd cmd) {
    Dept dept = assembler.create(generateCode(), cmd);
    return deptRepository.save(dept);
  }

  public int updateDept(Integer id, UpdateDeptCmd cmd) {
    Dept orig = deptValidator.assertDeptExists(id);
    String code = StringUtils.isNotBlank(orig.getCode()) ? orig.getCode() : generateCode();
    Dept dept = assembler.update(id, code, cmd);
    return deptRepository.save(dept);
  }

  private String generateCode() {
    return seqService.getSeq("DEPT", false);
  }

  public int deleteDept(Integer id) {
    Dept dept = deptValidator.assertDeptExists(id);
    List<Dept> children = deptRepository.findByPid(dept.getId());
    dept.canDelete(children);
    return deptRepository.deleteById(id);
  }
}
